package json;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.bson.Document;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import utils.GiteeUtils;
import utils.MongoUtils;
import utils.SystemUtils;

public class JSONUtilsChart {
	
	static ObjectMapper objectMapper = new ObjectMapper();

	public static void main(String[] args) throws Exception {
		renderChart();
	}

	private static void renderChart() throws Exception {
		List<Map<String, Object>> benchmarks = getBenchmarks();
		String benchmarksJson = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(benchmarks);
		System.out.println("benchmarksJson:"+benchmarksJson);
		
		List<Map<String, Object>> memAndCpuUsages = getMemAndCpuUsages();
		String memAndCpuUsagesJson = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(memAndCpuUsages);
		System.out.println("memAndCpuUsagesJson:"+memAndCpuUsagesJson);
		renderAndOpenHtml(benchmarks, memAndCpuUsages);
		
	}

	private static List<Map<String, Object>> getMemAndCpuUsages() {
		var memAndCpuUsageCollection = MongoUtils.getDatabase(JSONUtilsMemoryAndCpuUsage.JSON_UTILS_DATABASE)
				.getCollection(JSONUtilsMemoryAndCpuUsage.MEMORY_AND_CPU_USAGE_COLLECTION);
		var cursor = memAndCpuUsageCollection.aggregate(Arrays.asList(
			Document.parse("""
					{$sort:{updatedTime:-1}}
					""")
			, Document.parse("""
					{$group:{_id:"$jsonUtil",latest:{$first:"$$ROOT"}}}
					""")
			, Document.parse("""
					{$replaceRoot:{newRoot:"$latest"}}
					""")
		)).allowDiskUse(true).iterator();
		List<Map<String, Object>> memAndCpuUsages = new ArrayList<>();
		try(cursor){
			while(cursor.hasNext()) {
				var doc = cursor.next();
				System.out.println(doc.toJson());
				memAndCpuUsages.add(Map.of("jsonUtil", doc.getString("jsonUtil")
						, "messages", doc.get("messages")));
			}
		}
		return memAndCpuUsages;
	}

	private static List<Map<String, Object>> getBenchmarks() {
		var benchMarkCollection = MongoUtils.getDatabase(JSONUtilsBenchmark.JSON_UTILS_DATABASE)
			.getCollection(JSONUtilsBenchmark.BENCHMARK_COLLECTION);
		var cursor = benchMarkCollection.aggregate(Arrays.asList(
				Document.parse("""
						{$sort:{
						updatedTime:-1
						}}
						""")
				, Document.parse("""
						{$group:{
						_id:"$benchmarkName",
						latest:{$first:"$$ROOT"}
						}}
						""")
				, Document.parse("""
						{$replaceRoot:{
						newRoot:"$latest"
						}}
						""")
				)).allowDiskUse(true).iterator();
		List<Map<String, Object>> benchmarks = new ArrayList<>();
		try(cursor){
			while(cursor.hasNext()) {
				
				var doc = cursor.next();
				System.out.println(doc.toJson());
				benchmarks.add(Map.of("benchmarkName", doc.getString("benchmarkName")
						, "score", doc.getDouble("score")));
			}
		}
		return benchmarks;
	}
	private static void renderAndOpenHtml(List<Map<String, Object>> benchmarks, List<Map<String, Object>> memAndCpuUsages)
			throws URISyntaxException, IOException {
		// get all template files
		URL templatesDir = ClassLoader.getSystemResource("json/utils");
		Path sourcePath = Path.of(templatesDir.toURI());
		// create temp source dir
		File tempSourceDir = Files.createTempDirectory("temp_json_utils").toFile();
		tempSourceDir.deleteOnExit();
		FileUtils.copyDirectory(sourcePath.toFile(), tempSourceDir);
		// render files
		File indexHtmlFile = new File(tempSourceDir, "index.html");
		String indexHtmlContent = FileUtils.readFileToString(indexHtmlFile, StandardCharsets.UTF_8);
		indexHtmlContent = indexHtmlContent.replace("#{benchmarks}", objectMapper.writeValueAsString(benchmarks))
				.replace("#{memAndCpuUsages}", objectMapper.writeValueAsString(memAndCpuUsages));
		FileUtils.writeStringToFile(indexHtmlFile, indexHtmlContent, StandardCharsets.UTF_8);
		// open html file 
		SystemUtils.openFile(indexHtmlFile);
	}
}
